package cn.iocoder.yudao.module.enterprise.service.praxisProject;

import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.pojo.EmailInfo;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.SortingField;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.enterprise.controller.admin.praxisProject.vo.*;
import cn.iocoder.yudao.module.enterprise.dal.dataobject.praxisAnnex.EnterpriseAnnexDO;
import cn.iocoder.yudao.module.enterprise.dal.dataobject.praxisEntryChosen.EnterpriseEntryChosenDO;
import cn.iocoder.yudao.module.enterprise.dal.dataobject.praxisProject.EnterpriseEntryInfoDO;
import cn.iocoder.yudao.module.enterprise.dal.dataobject.praxisProject.EnterpriseProjectDO;
import cn.iocoder.yudao.module.enterprise.dal.dataobject.praxisProjectSchedule.EnterpriseProjectScheduleDO;
import cn.iocoder.yudao.module.enterprise.dal.mysql.praxisEntryChosen.EnterpriseEntryChosenMapper;
import cn.iocoder.yudao.module.enterprise.dal.mysql.praxisProject.EnterpriseEntryInfoMapper;
import cn.iocoder.yudao.module.enterprise.dal.mysql.praxisProject.EnterpriseProjectMapper;
import cn.iocoder.yudao.module.enterprise.dal.mysql.praxisProjectResult.EnterpriseProjectResultMapper;
import cn.iocoder.yudao.module.enterprise.service.praxisAnnex.EnterpriseAnnexService;
import cn.iocoder.yudao.module.enterprise.service.praxisProjectRecord.EnterpriseProjectRecordService;
import cn.iocoder.yudao.module.enterprise.service.praxisProjectSchedule.EnterpriseProjectScheduleService;
import cn.iocoder.yudao.module.system.api.permission.RoleApi;
import cn.iocoder.yudao.module.system.api.permission.dto.RoleDTO;
import cn.iocoder.yudao.module.system.api.userRole.AdminUserRoleApi;
import cn.iocoder.yudao.module.system.api.userRole.dto.UserRoleDTO;
import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.enterprise.enums.ErrorCodeConstants.*;

/**
 * 实践项目 Service 实现类
 *
 * @author 管理员
 */
@Service
@Validated
public class EnterpriseProjectServiceImpl implements EnterpriseProjectService {

    @Resource
    private EnterpriseProjectMapper enterpriseProjectMapper;
    @Resource
    private EnterpriseEntryInfoMapper enterpriseEntryInfoMapper;
    @Resource
    private EnterpriseEntryChosenMapper enterpriseEntryChosenMapper;
    @Resource
    private EnterpriseAnnexService enterpriseAnnexService;
    @Resource
    private EnterpriseProjectScheduleService enterpriseProjectScheduleService;
    @Resource
    private EnterpriseProjectRecordService enterpriseProjectRecordService;
    @Resource
    private EnterpriseProjectResultMapper enterpriseProjectResultMapper;
    @Resource
    private RoleApi roleApi;
    @Resource
    private AdminUserRoleApi adminUserRoleApi;
    @Value("${spring.profiles.active}")
    private String active;
    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createPraxisProject(EnterpriseProjectVO projectVO) {
        // 插入
        EnterpriseProjectDO praxisProjectDO=new EnterpriseProjectDO();
        BeanUtils.copyProperties(projectVO,praxisProjectDO);
        String username = SecurityFrameworkUtils.getLoginUser().getUsername();
        praxisProjectDO.setCreator(username);
        praxisProjectDO.setUpdater(username);
        praxisProjectDO.setUserId(SecurityFrameworkUtils.getLoginUser().getId());
        Integer maxWeight = NumberUtils.getInteger(enterpriseProjectMapper.getMaxWeight(null)) ;
        praxisProjectDO.setWeight(maxWeight+1);
        praxisProjectDO.setCompanyId(SecurityFrameworkUtils.getLoginUser().getCompanyId());
        enterpriseProjectMapper.insert(praxisProjectDO);
        List<EnterpriseAnnexVO> annexVOList = projectVO.getAnnexVOList();
        if(CollectionUtils.isNotEmpty(annexVOList)){
            List<EnterpriseAnnexDO> annexDTOList=new ArrayList<>();
            annexVOList.stream().forEach(m->{
                EnterpriseAnnexDO p=new EnterpriseAnnexDO();
                BeanUtils.copyProperties(m,p);
                p.setId(null);
                p.setRelationId(praxisProjectDO.getId());
                p.setRelationType(1);
                p.setCreator(username);
                p.setCreateTime(new Date());
                annexDTOList.add(p);
            });
            enterpriseAnnexService.batchSavePraxisAnnex(annexDTOList);
        }
        List<EnterpriseProjectScheduleVO> scheduleVOList = projectVO.getScheduleVOList();
        if(CollectionUtils.isNotEmpty(scheduleVOList)){
            List<EnterpriseProjectScheduleDO> scheduleDTOList=new ArrayList<>();
            scheduleVOList.stream().forEach(m->{
                EnterpriseProjectScheduleDO p=new EnterpriseProjectScheduleDO();
                BeanUtils.copyProperties(m,p);
                p.setId(null);
                p.setCreator(username);
                p.setProjectId(praxisProjectDO.getId());
                p.setCreateTime(new Date());
                scheduleDTOList.add(p);
            });
            enterpriseProjectScheduleService.batchSaveProjectSchedule(scheduleDTOList);
        }
        enterpriseProjectRecordService.saveProjectRecord(praxisProjectDO.getId(),1);
        // 返回
        return praxisProjectDO.getId();
    }

    @Override
    public void submitPraxisProject(Long id) {
        EnterpriseProjectDO praxisProjectDO=new EnterpriseProjectDO();
        String username = SecurityFrameworkUtils.getLoginUser().getUsername();
        praxisProjectDO.setId(id);
        praxisProjectDO.setUpdater(username);
        praxisProjectDO.setUpdateTime(new Date());
        praxisProjectDO.setExamineFlag("1");
        praxisProjectDO.setSubmitTime(new Date());
        enterpriseProjectMapper.updateById(praxisProjectDO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePraxisProject(EnterpriseProjectVO projectVO) {
        // 校验存在
        EnterpriseProjectDO projectDO = this.validatePraxisProjectExists(projectVO.getId());
        if(1==projectDO.getStatus()  ){
            throw exception(PRAXIS_PROJECT_NOT_DEL);
        }
        // 插入
        EnterpriseProjectDO praxisProjectDO=new EnterpriseProjectDO();
        BeanUtils.copyProperties(projectVO,praxisProjectDO);
        String username = SecurityFrameworkUtils.getLoginUser().getUsername();
        praxisProjectDO.setUpdater(username);
        praxisProjectDO.setExamineStatus("");
        praxisProjectDO.setExamineTime(null);
        praxisProjectDO.setExamineNotes("");
        enterpriseProjectMapper.updateById(praxisProjectDO);
        List<EnterpriseAnnexVO> annexVOList = projectVO.getAnnexVOList();
        enterpriseAnnexService.deletePraxisAnnexByProjectId(praxisProjectDO.getId(),1);
        if(CollectionUtils.isNotEmpty(annexVOList)){
            List<EnterpriseAnnexDO> annexDTOList=new ArrayList<>();
            annexVOList.stream().forEach(m->{
                EnterpriseAnnexDO p=new EnterpriseAnnexDO();
                BeanUtils.copyProperties(m,p);
                p.setId(null);
                p.setRelationId(praxisProjectDO.getId());
                p.setRelationType(1);
                p.setCreateTime(new Date());
                p.setCreator(username);
                annexDTOList.add(p);
            });
            enterpriseAnnexService.batchSavePraxisAnnex(annexDTOList);
        }
        List<EnterpriseProjectScheduleVO> scheduleVOList = projectVO.getScheduleVOList();
        enterpriseProjectScheduleService.deleteProjectScheduleByProjectId(praxisProjectDO.getId());
        if(CollectionUtils.isNotEmpty(scheduleVOList)){
            List<EnterpriseProjectScheduleDO> scheduleDTOList=new ArrayList<>();
            scheduleVOList.stream().forEach(m->{
                EnterpriseProjectScheduleDO p=new EnterpriseProjectScheduleDO();
                BeanUtils.copyProperties(m,p);
                p.setId(null);
                p.setCreator(username);
                p.setCreateTime(new Date());
                p.setProjectId(praxisProjectDO.getId());
                scheduleDTOList.add(p);
            });
            enterpriseProjectScheduleService.batchSaveProjectSchedule(scheduleDTOList);
        }
        if(0==praxisProjectDO.getStatus()){
            enterpriseProjectRecordService.saveProjectRecord(praxisProjectDO.getId(),2);
        }else {
            enterpriseProjectRecordService.saveProjectRecord(praxisProjectDO.getId(),3);
        }
    }

    @Override
    @TenantIgnore
    public void deletePraxisProject(Long id) {
        // 校验存在
        EnterpriseProjectDO projectDO = this.validatePraxisProjectExists(id);
        if(1==projectDO.getStatus()){
            throw exception(PRAXIS_PROJECT_NOT_DEL);
        }
        //删除关联数据(报名，公示)
        enterpriseEntryInfoMapper.deleteEntryStudentByProjectId(id);
        enterpriseEntryInfoMapper.delete(new QueryWrapper<EnterpriseEntryInfoDO>().eq("project_id",id));
        enterpriseEntryInfoMapper.deleteFeedBackByProjectId(id);
        enterpriseProjectResultMapper.deleteProjectResultByProjectId(id);
        // 删除
        enterpriseProjectMapper.deleteById(id);
        enterpriseProjectRecordService.saveProjectRecord(id,6);
    }

    public Boolean isAdminUser(){
        LoginUser user=SecurityFrameworkUtils.getLoginUser();
        List<UserRoleDTO> userRoleDTO=adminUserRoleApi.getUserRoleByUserId(user.getId());
        Set<String> roleCodes=new HashSet<>();
        for (UserRoleDTO userRole:userRoleDTO){
            RoleDTO roleDTO= roleApi.getRole(userRole.getRoleId());
            roleCodes.add(roleDTO.getCode());
        }
        for (String code:roleCodes) {
            if(code.equals(RoleCodeEnum.TENANT_ADMIN.getCode())) {
                return true;
            }
        }
        return  false;
    }

    @Override
    public void revertPraxisProject(Long id) {
        enterpriseProjectMapper.revertPraxisProject(id);
        enterpriseProjectRecordService.saveProjectRecord(id,7);
    }

    private EnterpriseProjectDO validatePraxisProjectExists(Long id) {
        EnterpriseProjectDO enterpriseProjectDO = enterpriseProjectMapper.selectById(id);
        if(null==enterpriseProjectDO){
            throw exception(PRAXIS_PROJECT_NOT_EXISTS);
        }
        if(!isAdminUser() && !enterpriseProjectDO.getCreator()
                .equals(SecurityFrameworkUtils.getLoginUser().getUsername())){
            //不是管理员
            throw exception(PRAXIS_PROJECT_NOT_AUTH);
        }
        if(isAdminUser() && !enterpriseProjectDO.getCompanyId()
                .equals(SecurityFrameworkUtils.getLoginUser().getCompanyId())){
            throw exception(PRAXIS_PROJECT_NOT_AUTH);
        }
        return enterpriseProjectDO;
    }

    @Override
    public EnterpriseProjectVO getPraxisProject(Long id) {
        EnterpriseProjectVO praxisProjectVO=null;
        EnterpriseProjectDO praxisProjectDO = enterpriseProjectMapper.getProjectInfoById(id);
        Boolean adminUser = this.isAdminUser();
        String username = SecurityFrameworkUtils.getLoginUser().getUsername();
        if(!adminUser && !praxisProjectDO.getCreator().equals(username)){
            throw exception(PRAXIS_PROJECT_NOT_AUTH);
        }
        if(null!=praxisProjectDO){
            praxisProjectVO=new EnterpriseProjectVO();
            BeanUtils.copyProperties(praxisProjectDO,praxisProjectVO);
            List<EnterpriseAnnexVO> annexVOList = enterpriseAnnexService.getPraxisAnnexListByProjectId(id, 1);
            praxisProjectVO.setAnnexVOList(annexVOList);
            List<EnterpriseProjectScheduleVO> scheduleVOList = enterpriseProjectScheduleService.getScheduleListByProjectId(id );
            praxisProjectVO.setScheduleVOList(scheduleVOList);
        }
        return praxisProjectVO;
    }

    @Override
    public List<EnterpriseProjectPageRespVO> getPraxisProjectList(String title,Integer queryType) {
        return enterpriseProjectMapper.getPraxisProjectList(title, SecurityFrameworkUtils.getLoginUser().getCompanyId(),queryType);
    }

    @Override
    public PageResult<EnterpriseProjectPageRespVO> getPraxisProjectPage(EnterpriseProjectPageReqVO pageReqVO) {
        // MyBatis Plus 查询
        IPage<EnterpriseProjectPageRespVO> mpPage = MyBatisUtils.buildPage(pageReqVO);
        // 转换返回
        Map<String, Object> params = new HashMap<>();
        if(StringUtils.isNotBlank(pageReqVO.getTitle())){
            params.put("title",pageReqVO.getTitle());
        }
        if(StringUtils.isNotBlank(pageReqVO.getCreator())){
            params.put("creator",pageReqVO.getCreator());
        }
        if(null!=pageReqVO.getScheduleType()){
            params.put("scheduleType",pageReqVO.getScheduleType());
        }
        if(null!=pageReqVO.getStatus()){
            params.put("status",pageReqVO.getStatus());
        }
        if(null!=pageReqVO.getExamineFlag()){
            params.put("examineFlag",pageReqVO.getExamineFlag());
        }
        if(null!=pageReqVO.getExamineStatus()){
            params.put("examineStatus",pageReqVO.getExamineStatus());
        }
        if(null !=pageReqVO.getDeleted()){
            params.put("deleted",pageReqVO.getDeleted());
        }else{
            params.put("deleted",0);
        }
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        Boolean adminUser = this.isAdminUser();
        if(!adminUser){
            params.put("creator",loginUser.getUsername());
        }
        params.put("companyId",loginUser.getCompanyId());
        mpPage.setRecords(enterpriseProjectMapper.getPraxisProjectPage(mpPage, params));
        return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
    }

    @Override
    public PageResult<EnterpriseEntryInfoPageRespVO> getEntryInfoPage(EnterpriseEntryInfoPageReqVO pageReqVO) {
        // MyBatis Plus 查询
        IPage<EnterpriseEntryInfoPageRespVO> mpPage = MyBatisUtils.buildPage(pageReqVO);
        // 转换返回
        Map<String, Object> params = new HashMap<>();
        if(StringUtils.isNotBlank(pageReqVO.getTitle())){
            params.put("title",pageReqVO.getTitle());
        }
        if(null!=pageReqVO.getScheduleType()){
            params.put("scheduleType",pageReqVO.getScheduleType());
        }
        if(StringUtils.isNotBlank(pageReqVO.getCreator())){
            params.put("creator",pageReqVO.getCreator());
        }
        mpPage.setRecords(enterpriseEntryInfoMapper.getEntryInfoPage(mpPage, params));
        return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
    }

    @Override
    public PageResult<EnterpriseEntryStudentPageRespVO> getEntryInfoPageByProjectId(EnterpriseEntryStudentPageReqVO pageReqVO) {
        // MyBatis Plus 查询
        IPage<EnterpriseEntryStudentPageRespVO> mpPage = MyBatisUtils.buildPage(pageReqVO);
        // 转换返回
        Map<String, Object> params = new HashMap<>();
        params.put("projectId",pageReqVO.getProjectId());
        params.put("scheduleType",pageReqVO.getScheduleType());
        if(null!=pageReqVO.getLookStatus()){
            params.put("lookStatus",pageReqVO.getLookStatus());
        }
        if(null!=pageReqVO.getCheckStatus()){
            params.put("checkStatus",pageReqVO.getCheckStatus());
        }
        if(StringUtils.isNotBlank(pageReqVO.getTeamName())){
            params.put("teamName",pageReqVO.getTeamName());
        }
        if(StringUtils.isNotBlank(pageReqVO.getStudentName())){
            params.put("studentName",pageReqVO.getStudentName());
        }
        if(StringUtils.isNotBlank(pageReqVO.getSchoolName())){
            params.put("schoolName",pageReqVO.getSchoolName());
        }
        mpPage.setRecords(enterpriseEntryInfoMapper.getEntryInfoPageByProjectId(mpPage, params));
        return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
    }

    @Override
    public List<EnterpriseEntryStudentPageRespVO> getEntryInfoPageByProjectList(EnterpriseEntryStudentExcelReqVO pageReqVO) {
        Map<String, Object> params = new HashMap<>();
        params.put("projectId",pageReqVO.getProjectId());
        params.put("scheduleType",pageReqVO.getScheduleType());
        if(null!=pageReqVO.getLookStatus()){
            params.put("lookStatus",pageReqVO.getLookStatus());
        }
        if(null!=pageReqVO.getCheckStatus()){
            params.put("checkStatus",pageReqVO.getCheckStatus());
        }
        if(StringUtils.isNotBlank(pageReqVO.getTeamName())){
            params.put("teamName",pageReqVO.getTeamName());
        }
        if(StringUtils.isNotBlank(pageReqVO.getStudentName())){
            params.put("studentName",pageReqVO.getStudentName());
        }
        if(StringUtils.isNotBlank(pageReqVO.getSchoolName())){
            params.put("schoolName",pageReqVO.getSchoolName());
        }
        return enterpriseEntryInfoMapper.getEntryInfoPageByProjectList( params);
    }

    @Override
    public PageResult<EnterpriseFeedBackVO> getFeedBackPageByProjectId(EnterpriseFeedBackPageReqVO pageVO) {
        // MyBatis Plus 查询
        SortingField sortingField = new SortingField();
        sortingField.setField("t.id");
        sortingField.setOrder("desc");
        pageVO.setSortField(sortingField);
        IPage<EnterpriseFeedBackVO> mpPage = MyBatisUtils.buildPage(pageVO);
        // 转换返回
        Map<String, Object> params = new HashMap<>();
        params.put("projectId",pageVO.getProjectId());
        params.put("feedbackStatus",1);
        mpPage.setRecords(enterpriseEntryInfoMapper.getFeedBackPageByProjectId(mpPage, params));
        return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
    }
    @Override
    public List<EnterpriseProjectRecordVO> getRecordByProjectId(Long id) {
        return enterpriseProjectRecordService.getPraxisProjectRecordList(id);
    }

    @Override
    public void updateRateScore(EnterpriseProjectSourceUpdateVO updateVO) {
        Long num= enterpriseEntryInfoMapper.getScheduleByEntryId(updateVO.getEntryId());
        if(null==num || num==0){
            throw exception(PRAXIS_PROJECT_SUCHED_END);
        }
        enterpriseEntryInfoMapper.updateRateScore(updateVO.getEntryId(), updateVO.getRateScore()
                ,SecurityFrameworkUtils.getLoginUser().getUsername());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchUpdateStatus(EnterpriseProjectUpdateVO updateVO) {

        List<EnterpriseEntryInfoBaseVO> list = enterpriseEntryInfoMapper.getEntryInfoById(updateVO.getIds());
        //类型;1:入选;2:撤销
        String username = SecurityFrameworkUtils.getLoginUser().getUsername();
        if(CollectionUtils.isNotEmpty(list)){
            EnterpriseEntryInfoBaseVO firstEntInfo = list.stream().findFirst().orElse(null);
            Integer scheduleType=firstEntInfo.getScheduleType();
            Integer nextScheduleType=NumberUtils.getInteger(firstEntInfo.getNextScheduleType(),scheduleType+1);
            Long projectId=firstEntInfo.getProjectId();
            EnterpriseProjectScheduleVO schedule = enterpriseEntryInfoMapper.getScheduleByProjectId(projectId, scheduleType);
            if(null==schedule){
                ErrorCode PRAXIS_PROJECT_ENTRY_EXIST1= new ErrorCode(1004001034,  getScheduleTypeName(scheduleType)+"不存在,请先添加赛程");
                throw exception(PRAXIS_PROJECT_ENTRY_EXIST1);
            }
            if(new Date().before(schedule.getStartTime()) || new Date().after(schedule.getEndTime())){
                throw exception(PRAXIS_PROJECT_SUCHED_END);
            }
            Integer isSendEmail = NumberUtils.getInteger(updateVO.getIsSendEmail(),0);
            if(updateVO.getType()==0){
                List<Long> nextIds = list.stream().filter(m -> (null != m.getNextEntryId())).map(m -> m.getNextEntryId()).collect(Collectors.toList());
                if(CollectionUtils.isNotEmpty(nextIds)){
                    enterpriseEntryInfoMapper.deleteEntryInfoById(nextIds);
                }
                enterpriseEntryChosenMapper.deleteEntryChosenById(updateVO.getIds());
            }else if(updateVO.getType()==1){
                if(4==scheduleType){
                    if(StringUtils.isBlank(updateVO.getPrizeName()) ||null==updateVO.getPrizeCeremony() ||null==updateVO.getPrizeType()){
                        throw exception(PRAXIS_PROJECT_ENTRY_NOTNULL);
                    }
                }
                list.stream().forEach(m->{
                    if(null!=m.getCheckStatus() && 1==m.getCheckStatus()){
                        ErrorCode PRAXIS_PROJECT_ENTRY_EXIST1= new ErrorCode(1004001032, m.getTeamName()+"已入选,不能重复添加");
                        throw exception(PRAXIS_PROJECT_ENTRY_EXIST1);
                    }
                    if(nextScheduleType<5){
                        Long aLong = enterpriseEntryInfoMapper.selectCount(new QueryWrapper<EnterpriseEntryInfoDO>()
                                .eq("project_id", m.getProjectId())
                                .eq("schedule_type", nextScheduleType)
                                .eq("student_id", m.getStudentId()).eq("deleted", 0));
                        if(null!= aLong && aLong>0){
                            ErrorCode PRAXIS_PROJECT_ENTRY_EXIST1= new ErrorCode(1004001029, m.getTeamName()+"已入选,不能重复添加");
                            throw exception(PRAXIS_PROJECT_ENTRY_EXIST1);
                        }
                    }
                });
                Date date = new Date();
                list.stream().forEach(m->{
                    EnterpriseEntryChosenDO c=new EnterpriseEntryChosenDO();
                    c.setEntryId(m.getId());
                    c.setIsSendEmail(isSendEmail);
                    c.setOtherNotes(updateVO.getOtherNotes());
                    c.setLinkMobile(updateVO.getLinkMobile());
                    c.setLinkName(updateVO.getLinkName());
                    c.setCreateTime(date);
                    c.setCreator(username);
                    c.setUpdater(username);
                    c.setUpdateTime(date);
                    if(scheduleType<4){
                        EnterpriseEntryInfoDO e=new EnterpriseEntryInfoDO();
                        BeanUtils.copyProperties(m,e);
                        e.setId(null);
                        e.setLookStatus(1);
                        e.setScheduleType(nextScheduleType);
                        e.setEntryStatus(2);
                        e.setAnnexUrl(null);
                        e.setAnnexName(null);
                        e.setRateScore(null);
                        e.setCreateTime(date);
                        e.setUpdateTime(date);
                        e.setCreator(username);
                        e.setUpdater(username);
                        enterpriseEntryInfoMapper.insert(e);
                    }else{
                        c.setPrizeCeremony(updateVO.getPrizeCeremony());
                        c.setPrizeName(updateVO.getPrizeName());
                        c.setPrizeType(updateVO.getPrizeType());
                    }
                    enterpriseEntryChosenMapper.insert(c);
                });
                if(1==isSendEmail){
                    EnterpriseProjectScheduleVO scheduleVO =null;
                    if(5!=nextScheduleType){
                        scheduleVO = enterpriseEntryInfoMapper.getScheduleByProjectId(firstEntInfo.getProjectId(), nextScheduleType);
                        if(null==scheduleVO){
                            scheduleVO=new EnterpriseProjectScheduleVO();
                        }
                    }
                    List<Long> firstIds = list.stream().filter(m -> (null != m.getFirstEntryId())).map(m -> m.getFirstEntryId()).collect(Collectors.toList());
                    List<EnterpriseEmailInfoVO> sList = enterpriseEntryInfoMapper.getEntryStudentListByIds(firstIds);
                    if(CollectionUtils.isNotEmpty(sList)){
                        for (EnterpriseEmailInfoVO m : sList) {
                            if(StringUtils.isBlank(m.getEmail())){
                                continue;
                            }
                            m.setScheduleType(nextScheduleType);
                            m.setLinkMobile(updateVO.getLinkMobile());
                            m.setLinkName(updateVO.getLinkName());
                            m.setOtherNotes(updateVO.getOtherNotes());
                            if(4!=scheduleType){
                                m.setClosingDate(scheduleVO.getClosingDate());
                                m.setStartTime(scheduleVO.getStartTime());
                                m.setEndTime(scheduleVO.getEndTime());
                            }else{
                                m.setPrizeCeremony(updateVO.getPrizeCeremony());
                                m.setPrizeName(updateVO.getPrizeName());
                                m.setPrizeType(updateVO.getPrizeType());
                            }
                            sendHtmlMail(m);
                        }
                    }
                }
            }
            enterpriseEntryInfoMapper.updateCheckStatus(updateVO.getIds(),username,updateVO.getType());
        }
    }

    @Override
    public List<EnterpriseEntryStudentVO> getEntryStudentList(Long entryId) {
        List<EnterpriseEntryStudentVO> entryStudentList = enterpriseEntryInfoMapper.getEntryStudentList(entryId);
        return entryStudentList;
    }

    @Override
    public EnterpriseEntryInfoBaseVO getEntryInfoById(Long id) {
        List<EnterpriseEntryInfoBaseVO> list = enterpriseEntryInfoMapper.getEntryInfoById(Arrays.asList(id));
        EnterpriseEntryInfoBaseVO vo=  CollectionUtils.isNotEmpty(list)?list.get(0) : null;
        if(null!=vo && 1==vo.getLookStatus()){
            EnterpriseEntryInfoDO entryInfoDO=new EnterpriseEntryInfoDO();
            entryInfoDO.setId(id);
            entryInfoDO.setLookStatus(2);
            enterpriseEntryInfoMapper.updateById(entryInfoDO);
        }
        return vo;
    }

    @Override
    public EnterpriseProjectScheduleVO getNextScheduleByProjectId(Long projectId, Integer scheduleType) {
        return enterpriseProjectScheduleService.getNextScheduleByProjectId(projectId,scheduleType);
    }

    @Override
    public void updateShowFlag(Long id) {
        // 校验存在
        EnterpriseProjectDO projectDO = this.validatePraxisProjectExists(id);
        Integer showFlag=NumberUtils.getInteger(projectDO.getShowFlag(),0);
        if(0==showFlag){
            showFlag=1;
        }else{
            showFlag=0;
        }
        enterpriseProjectMapper.update(Wrappers.<EnterpriseProjectDO>lambdaUpdate().set(EnterpriseProjectDO::getShowFlag,showFlag)
                .eq(EnterpriseProjectDO::getId,id));
    }

    @Override
    public void saveProjectScheduleVO(EnterpriseProjectVO projectVO) {
        this.validatePraxisProjectExists(projectVO.getId());
        List<EnterpriseProjectScheduleVO> scheduleVOList=projectVO.getScheduleVOList();
        String msg = validateScheduleTime(scheduleVOList,2);
        if(StringUtils.isNotBlank(msg)){
            ErrorCode PRAXIS_PROJECT_NOT_DOUBLE= new ErrorCode(1004001036, msg);
            throw exception(PRAXIS_PROJECT_NOT_DOUBLE);
        }
        msg = validateUpdateSchedule(scheduleVOList,projectVO.getId());
        if(StringUtils.isNotBlank(msg)){
            ErrorCode PRAXIS_PROJECT_NOT_DOUBLE= new ErrorCode(1004001037, msg);
            throw exception(PRAXIS_PROJECT_NOT_DOUBLE);
        }
        enterpriseProjectScheduleService.deleteProjectScheduleByProjectId(scheduleVOList.get(0).getProjectId());
        List<EnterpriseProjectScheduleDO> scheduleDTOList=new ArrayList<>();
        scheduleVOList.stream().forEach(m->{
            EnterpriseProjectScheduleDO p=new EnterpriseProjectScheduleDO();
            BeanUtils.copyProperties(m,p);
            p.setId(null);
            p.setCreator(SecurityFrameworkUtils.getLoginUser().getUsername());
            p.setCreateTime(new Date());
            scheduleDTOList.add(p);
        });
        enterpriseProjectScheduleService.batchSaveProjectSchedule(scheduleDTOList);
    }


    @Override
    public String validateScheduleTime(List<EnterpriseProjectScheduleVO> scheduleVOList ,int type){
        EnterpriseProjectScheduleVO scheduleVO_1 = scheduleVOList.stream().filter(m -> (1 == m.getScheduleType())).findFirst().orElse(null);
        EnterpriseProjectScheduleVO scheduleVO_4 = scheduleVOList.stream().filter(m -> (4 == m.getScheduleType())).findFirst().orElse(null);
        if(null==scheduleVO_1 || null== scheduleVO_1.getStartTime() || null== scheduleVO_1.getEndTime()){
            return "遴选时间不能为空";
        }
        if(null==scheduleVO_4 || null== scheduleVO_4.getStartTime()|| null== scheduleVO_4.getEndTime() ){
            return "决赛时间不能为空";
        }
        if(type==1 && scheduleVO_1.getStartTime().before(new Date())){
            return "遴选开始时间必须大于当前时间";
        }
        if(scheduleVO_1.getStartTime().after(scheduleVO_1.getClosingDate()) ||scheduleVO_1.getEndTime().before(scheduleVO_1.getClosingDate())){
            return "遴选截止上传时间必须在开始时间和结束时间之间";
        }
        if(scheduleVO_4.getStartTime().after(scheduleVO_4.getClosingDate()) ||scheduleVO_4.getEndTime().before(scheduleVO_4.getClosingDate())){
            return "决赛截止上传时间必须在开始时间和结束时间之间";
        }
        if( scheduleVO_4.getStartTime().before(scheduleVO_1.getEndTime())){
            return "决赛开始时间必须大于遴选结束时间";
        }
        EnterpriseProjectScheduleVO scheduleVO_2 = scheduleVOList.stream().filter(m -> (2 == m.getScheduleType())).findFirst().orElse(null);
        if(null!=scheduleVO_2 ){
            if(scheduleVO_2.getStartTime().after(scheduleVO_2.getClosingDate()) ||scheduleVO_2.getEndTime().before(scheduleVO_2.getClosingDate())){
                return "初赛截止上传时间必须在开始时间和结束时间之间";
            }
            if( scheduleVO_2.getStartTime().before(scheduleVO_1.getEndTime())){
                return "初赛开始时间必须大于遴选结束时间";
            }
            if( scheduleVO_4.getStartTime().before(scheduleVO_2.getEndTime())){
                return "决赛开始时间必须大于初赛结束时间";
            }
        }
        EnterpriseProjectScheduleVO scheduleVO_3 = scheduleVOList.stream().filter(m -> (3 == m.getScheduleType())).findFirst().orElse(null);
        if(null!=scheduleVO_3 ){
            if(scheduleVO_3.getStartTime().after(scheduleVO_3.getClosingDate()) ||scheduleVO_3.getEndTime().before(scheduleVO_3.getClosingDate())){
                return "复赛截止上传时间必须在开始时间和结束时间之间";
            }
            if( null!=scheduleVO_2 && scheduleVO_3.getStartTime().before(scheduleVO_2.getEndTime())){
                return "复赛开始时间必须大于初赛结束时间";
            }
            if( scheduleVO_4.getStartTime().before(scheduleVO_3.getEndTime())){
                return "决赛开始时间必须大于复赛结束时间";
            }
        }
        return "";
    }

    @Override
    @TenantIgnore
    public Integer getProjectCountByTitle(String title, Long id) {
        return NumberUtils.getInteger(enterpriseProjectMapper.getProjectCountByTitle(title,id));
    }

    @Override
    public String validateUpdateSchedule(List<EnterpriseProjectScheduleVO> scheduleVOList, Long projectId) {
        List<EnterpriseProjectScheduleVO> scheduleList= enterpriseProjectScheduleService.getScheduleListByProjectId(projectId);
        if(CollectionUtils.isNotEmpty(scheduleList)){
            EnterpriseProjectScheduleVO scheduleVO_1 = scheduleVOList.stream().filter(m -> (1 == m.getScheduleType())).findFirst().orElse(null);
            EnterpriseProjectScheduleVO schedule_1 = scheduleList.stream().filter(m -> (1 == m.getScheduleType())).findFirst().orElse(null);
            if(schedule_1.getStartTime().before(new Date()) &&
                    (scheduleVO_1.getStartTime().getTime()!= schedule_1.getStartTime().getTime()
                            ||scheduleVO_1.getEndTime().getTime()!= schedule_1.getEndTime().getTime()
                            ||scheduleVO_1.getClosingDate().getTime()!= schedule_1.getClosingDate().getTime()
                    )){
                return "遴选阶段已开始,不能修改";
            }
            EnterpriseProjectScheduleVO scheduleVO_2 = scheduleVOList.stream().filter(m -> (2 == m.getScheduleType())).findFirst().orElse(null);
            EnterpriseProjectScheduleVO schedule_2 = scheduleList.stream().filter(m -> (2 == m.getScheduleType())).findFirst().orElse(null);
            if(null!=scheduleVO_2 && null==schedule_2 && scheduleVO_2.getStartTime().before(new Date())){
                return "初赛阶段开始时间必须大于当前时间";
            }
            if(null!=scheduleVO_2 && null!=schedule_2 ){
                if(schedule_2.getStartTime().before(new Date()) &&
                        (scheduleVO_2.getStartTime().getTime()!= schedule_2.getStartTime().getTime()
                                ||scheduleVO_2.getEndTime().getTime()!= schedule_2.getEndTime().getTime()
                                ||scheduleVO_2.getClosingDate().getTime()!= schedule_2.getClosingDate().getTime()
                        )){
                    return "初赛阶段已开始,不能修改";
                }
            }
            EnterpriseProjectScheduleVO scheduleVO_3 = scheduleVOList.stream().filter(m -> (3 == m.getScheduleType())).findFirst().orElse(null);
            EnterpriseProjectScheduleVO schedule_3 = scheduleList.stream().filter(m -> (3 == m.getScheduleType())).findFirst().orElse(null);
            if(null!=scheduleVO_3 && null==schedule_3 && scheduleVO_3.getStartTime().before(new Date())){
                return "复赛阶段开始时间必须大于当前时间";
            }
            if(null!=scheduleVO_3 && null!=schedule_3 ){
                if(schedule_3.getStartTime().before(new Date()) &&
                        (scheduleVO_3.getStartTime().getTime()!= schedule_3.getStartTime().getTime()
                                ||scheduleVO_3.getEndTime().getTime()!= schedule_3.getEndTime().getTime()
                                ||scheduleVO_3.getClosingDate().getTime()!= schedule_3.getClosingDate().getTime()
                        )){
                    return "复赛阶段已开始,不能修改";
                }
            }

            EnterpriseProjectScheduleVO scheduleVO_4 = scheduleVOList.stream().filter(m -> (4 == m.getScheduleType())).findFirst().orElse(null);
            EnterpriseProjectScheduleVO schedule_4 = scheduleList.stream().filter(m -> (4 == m.getScheduleType())).findFirst().orElse(null);
            if(schedule_4.getStartTime().before(new Date()) &&
                    (scheduleVO_4.getStartTime().getTime()!= schedule_4.getStartTime().getTime()
                            ||scheduleVO_4.getEndTime().getTime()!= schedule_4.getEndTime().getTime()
                            ||scheduleVO_4.getClosingDate().getTime()!= schedule_4.getClosingDate().getTime()
                    )){
                return "决赛阶段已开始,不能修改";
            }
        }
        return "";
    }

    public String getScheduleTypeName(Integer scheduleType){
        String scheduleTypeName;
        switch (scheduleType){
            case 1:
                scheduleTypeName="遴选";
                break;
            case 2:
                scheduleTypeName="初赛";
                break;
            case 3:
                scheduleTypeName="复赛";
                break;
            case 4:
                scheduleTypeName="决赛";
                break;
            default:
                scheduleTypeName="奖项";
        }
        return scheduleTypeName;
    }

    @Async
    public void sendHtmlMail(EnterpriseEmailInfoVO entryVO){
        EmailInfo emailInfo=new EmailInfo();
        String scheduleTypeName=getScheduleTypeName(entryVO.getScheduleType());
        emailInfo.setToUser(entryVO.getEmail());
        String companyName=StrUtils.toStr(entryVO.getCompanyName());
        if(StringUtils.isNotBlank(companyName)){
            companyName+="-";
        }
        emailInfo.setSubject("【数据学徒】"+companyName+StrUtils.toStr(entryVO.getProjectTitle())+"-"+StrUtils.toStr(entryVO.getTeamName())+"-"+scheduleTypeName+"入选通知");
        emailInfo.setEnvironment(active);
        StringBuffer str=new StringBuffer();
        str.append("<!DOCTYPE html><html><head><meta charset='UTF-8'></head><body>");
        if(5!=entryVO.getScheduleType()){
            str.append("<p >您好，我们很高兴的通知您已入选 "+StrUtils.toStr(entryVO.getProjectTitle())+"-"+scheduleTypeName+"。具体安排如邮件下方，请于截止日期前上传"+DateUtils.format(entryVO.getClosingDate(),DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)+"作品!</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>比赛阶段:"+scheduleTypeName+"</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>比赛时间:"+DateUtils.format(entryVO.getStartTime(),DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)+"至"+DateUtils.format(entryVO.getEndTime(),DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)+"</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>作品截止上传时间:"+DateUtils.format(entryVO.getClosingDate(),DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)+"</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>其他:"+StrUtils.toStr(entryVO.getOtherNotes())+"</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>联系人:"+StrUtils.toStr(entryVO.getLinkName())+"</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>联系方式:"+StrUtils.toStr(entryVO.getLinkMobile())+"</p>");
        }else{
            //1:线上颁奖;2:线下颁奖
            String prizeTypeName="线上颁奖";
            if(2==entryVO.getPrizeType()){
                prizeTypeName="线下颁奖";
            }
            emailInfo.setSubject("【数据学徒】"+companyName+StrUtils.toStr(entryVO.getProjectTitle())+"-"+StrUtils.toStr(entryVO.getTeamName())+"-"+scheduleTypeName+"获奖通知");
            str.append("<p>您好，我们很高兴的通知您已获得"+StrUtils.toStr(entryVO.getProjectTitle())+"奖励。具体颁奖安排如邮件下方!</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>奖项:"+entryVO.getPrizeName()+"</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>颁奖典礼:"+DateUtils.format(entryVO.getPrizeCeremony() ,DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) +"</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>颁奖类型:"+prizeTypeName+"</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>其他:"+StrUtils.toStr(entryVO.getOtherNotes())+"</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>联系人:"+StrUtils.toStr(entryVO.getLinkName())+"</p>");
            str.append("<p style='text-align:; font-size: 18px; padding-right: 20px;'>联系方式:"+StrUtils.toStr(entryVO.getLinkMobile())+"</p>");
        }
        str.append("<p style='text-align:right; padding-right: 20px;'> <img  width='200px' src='https://demo-oss.oss-cn-beijing.aliyuncs.com/jpg/9fad169ed78a492080a3800a41d97b68.jpg'/></p>");
        str.append("<p style='text-align:right; padding-right: 20px;'>电话：0755-23372612/0755-23372649</p>");
        str.append("<p style='text-align:right; padding-right: 20px;'>contact@datarer.com</p>");
        str.append("<p style='text-align:right; padding-right: 20px;'>www.datarer.com</p>");
        str.append("</body></html>");
        emailInfo.setContent(str.toString());
        threadPoolTaskExecutor.execute(()->{
            HttpUtils.doPost("http://127.0.0.1:8085/demo/task/sendMail",JSONObject.toJSONString(emailInfo));
        });
    }

    @Override
    public EnterpriseProjectCountVO getPraxisProjectCount(Long id) {
        EnterpriseProjectCountVO projectCount = enterpriseProjectMapper.getPraxisProjectCount(id);
        List<String> lastMonth12 = DateUtils.getLastMonth12();
        List<EnterpriseProjectViewCountVO> projectViewCount = enterpriseProjectMapper.getPraxisProjectViewCount(id, lastMonth12);
        if(CollectionUtils.isNotEmpty(projectViewCount)){
            List<EnterpriseProjectViewCountVO> newViewList=new ArrayList<>();
            for (String month:lastMonth12){
                EnterpriseProjectViewCountVO v = projectViewCount.stream().filter(m -> month.equals(m.getViewMonth())).findFirst().orElse(null);
                if(null==v){
                    EnterpriseProjectViewCountVO pv=new EnterpriseProjectViewCountVO();
                    pv.setNum(0L);
                    pv.setViewMonth(month);
                    newViewList.add(pv);
                }else{
                    newViewList.add(v);
                }
            }
            projectCount.setViewCountList(newViewList);
        }
        projectCount.setMajorList(enterpriseProjectMapper.getPraxisProjectMajorCount(id));
        return projectCount;
    }
}
